// 泛型 
// 应用场景：泛型函数、泛型接口、泛型类

// 1-1. 需求：封装函数，传入字符串，直接返回字符串
function returnStr(arg:string):string{
	return arg
}
console.log(returnStr('Hello'));


//1-2. 需求：封装函数，传入数字，直接返回数字
function returnNum(arg:number):number{
	return arg
}
console.log(returnNum(1234));

//1-3. 需求：封装函数，传入布尔值，直接返回布尔值

// 1-4 单泛型函数
function returnItem<T>(arg:T):T{
	return arg
}
console.log(returnItem<string>('world'));
console.log(returnItem<boolean>(true));


// 2-1 需求：封装函数，传入[7,'seven'] ，返回['seven',7]

function swap1(arg:[number,string]):[string,number]{
	return [arg[1],arg[0]]
}

console.log(swap1([6,'six']));

// 2-2 需求：封装函数，传入[1,true]，返回[true,1]
function swap2(arg:[number,boolean]):[boolean,number]{
	return [arg[1],arg[0]]
}
console.log(swap2([0,false]));

// 2-3 多泛型函数
function swap<T,U>(arg:[T,U]):[U,T]{
	return [arg[1],arg[0]]
}
console.log(swap([7,'seven']));




// 3-1 需求：从服务器端加载了一个带有商品数据的JSON包，请为它设定明确的类型约束
// 假设这是某次get请求，从服务器加载到的数据
interface GoodsType {
	name:string
	price:number
}
interface DataType1 {
	results:Array<GoodsType>
}
interface ResType1 {
	status:number
	data:DataType1
}
let res1:ResType1 = {
	status:200,
	data:{
		results:[
			{name:'商品名称1',price:199},
			{name:'商品名称2',price:19.9},
			{name:'商品名称3',price:1.99},
			{name:'商品名称4',price:1999},
		]
	}
}


// 3-2 需求：为加载到的公司数据，给出明确类型约束
interface CompanyType {
	title:string
	location:string
}
interface DataType2{
	results:Array<CompanyType>
}
interface ResType2{
	status:number
	data:DataType2
}
let res2:ResType2 = {
	status:200,
	data:{
		results:[
			{title:'Alimama',location:'余杭区'},
			{title:'Tencent',location:'深圳大学旁边'},
			{title:'ByteDance',location:'xxxx'}
		]
	}
}

// 3-3 泛型接口封装
interface DataType <T>{
	results:Array<T>
}
interface ResType <T>{
	status:number
	data:DataType<T>
}

let res3:ResType<CompanyType> = {
	status:200,
	data:{
		results:[
			{title:'Alimama',location:'余杭区'},
			{title:'Tencent',location:'深圳大学旁边'},
			{title:'ByteDance',location:'xxxx'}
		]
	}
}


// 3-4 为岗位数据添加明确类型约束
interface JobType {
	jobname:string
	salary:number
}

let res4:ResType<JobType> = {
	status:200,
	data:{
		results:[
			{jobname:'客户端开发',salary:19999},
			{jobname:'服务端开发',salary:9999},
			{jobname:'产品经历',salary:999},
		]
	}
}


// 泛型约束，如果不期望泛型的应用太过广泛
// 用一个接口来约定纯数字的数组、或者纯字符串的数组
type Param = string|number
interface LimitType <T extends Param>{
	[index:number]:T
}
let strArr:LimitType<string> = ['1','2']
let numArr:LimitType<number> = [3,4,5]
// let boolArr:LimitType<boolean> = [true]  //此处会告警


// 泛型约束 与  索引类型
// 需求：封装函数，接收两个参数 【键值对对象】、【键名key】，期望以键名为条件成功提取对应的值

let user1 = {name:'三丰',age:100}
// getValue(user,'name')  //要求返回三丰

// function getValue(obj:Object,key:string){
// 	return obj[key]  //Object对象，跟key之间没有正确的关联关系
// }

function getValue<T,U extends keyof T>(obj:T,key:U){
	return obj[key]  
}
console.log(getValue(user1,'name'));